/**
 * 编程题第三题修改，
 * 将两个数组 int num_in_rank[], int num_in_suit[]
 * 改为二维数组
 */
#include <stdbool.h> /* C99 only */
#include <stdio.h>
#include <stdlib.h>

// 13个点数
#define NUM_RANKS 13
// 4个花色
#define NUM_SUITS 4
// 手中的5张牌
#define NUM_CARDS 5
//点数在第1列
#define RANK 0
//花色在第2列
#define SUIT 1

/* prototypes */
void read_cards();
void analyze_hand();
void print_result(void);

// external variables
int hand[NUM_CARDS][2];

// 分别是 同花大顺， 小A顺，顺子，同花，四条，三条，
bool royal, wheel, straight, flush, four, three;
// 对子
int pairs; /* can be 0, 1, or 2 */

int main(void) {
    // 对应点数牌的数量，0~12对应2~K，A
    int num_in_rank[NUM_RANKS];
//对应的花色，分别是方块、梅花、红桃和黑桃
    int num_in_suit[NUM_SUITS];
    for(;;) {
        // 读取手牌
        read_cards();
        // 分析手牌
        analyze_hand();
        // 打印结果
        print_result();
    }
}

void read_cards() {
    char ch, rank_ch, suit_ch;
    int rank, suit;
    bool bad_card, duplicate;
    int cards_read = 0;

    // 初始化数据
    for (rank = 0; rank < NUM_CARDS; rank++) {
        hand[rank][RANK] = -1;
        hand[rank][SUIT] = -1;
    }
    // 初始化数据
    for (suit = 0; suit < NUM_SUITS; suit++) {
        bad_card = false;
    }

    while (cards_read < NUM_CARDS) {
        bad_card = false;

        printf("Enter a card: ");

        rank_ch = getchar();
        switch (rank_ch) {
            case '0':
                exit(EXIT_SUCCESS);
            case '2': rank = 0;
                break;
            case '3': rank = 1;
                break;
            case '4': rank = 2;
                break;
            case '5': rank = 3;
                break;
            case '6': rank = 4;
                break;
            case '7': rank = 5;
                break;
            case '8': rank = 6;
                break;
            case '9': rank = 7;
                break;
            case 't': case 'T': rank = 8;
                break;
            case 'j': case 'J': rank = 9;
                break;
            case 'q': case 'Q': rank = 10;
                break;
            case 'k': case 'K': rank = 11;
                break;
            case 'a': case 'A': rank = 12;
                break;
            default:
                bad_card = true;
        }

        suit_ch = getchar();
        switch (suit_ch) {
            case 'c':
            case 'C':
                suit = 0;
                break;
            case 'd':
            case 'D':
                suit = 1;
                break;
            case 'h':
            case 'H':
                suit = 2;
                break;
            case 's':
            case 'S':
                suit = 3;
                break;
            default:
                bad_card = true;
        }

        while ((ch = getchar()) != '\n')
            if(ch != ' ') bad_card = true;

        if (bad_card) {
            printf("Bad card, ignored.\n");
            continue;
        }

        // 校验重复手牌
        duplicate = false;
        for (int i = 0; i < NUM_CARDS; ++i) {
            if (hand[i][RANK] == rank && hand[i][SUIT] == suit) {
                printf("Duplicate card; ignored.\n");
                duplicate = true;
                break;
            }
        }
        if (duplicate) {
            continue;
        }

        hand[cards_read][RANK] = rank;
        hand[cards_read][SUIT] = suit;
        cards_read++;
    }
}
void analyze_hand() {
    int rank, suit;

    royal = false;
    wheel = false;
    straight = true;
    flush = true;
    four = false;
    three = false;
    pairs = 0;

    //sort cards by rank
    for (int i = 1; i < NUM_CARDS; ++i) {
        for (int j = 0; j < NUM_CARDS - i; ++j) {
            if(hand[j][RANK] > hand[j + 1][RANK]) {
                int cur_rank = hand[j][RANK];
                int cur_suit = hand[j][SUIT];
                hand[j][RANK] = hand[j + 1][RANK];
                hand[j][SUIT] = hand[j + 1][SUIT];
                hand[j + 1][RANK] = cur_rank;
                hand[j + 1][SUIT] = cur_suit;
            }
        }
    }


    /* check for flush */
    for (suit = 1; suit < NUM_SUITS; suit++) {
//        if(num_in_suit[suit] == NUM_CARDS)
        // 和上一个元素比较，必须全部相等
        if (hand[suit - 1][1] != hand[suit][1])
            flush = false;
    }

    /* check for straight */
    for (int i = 0; i < NUM_CARDS - 1; i++) {
        // 发现任意一对不连续就否定顺子
        if (hand[i][RANK] + 1 != hand[i + 1][RANK]) {
            straight = false;
            break;
        }
    }

    // 判断同花大顺
    if(flush && straight && hand[0][RANK] == 8) {
        royal = true;
    } 
    // 判断小A顺
    if(!straight) {
        if(hand[0][RANK] == 0 && hand[1][RANK] == 1 
            && hand[2][RANK] == 2 && hand[3][RANK] == 3 
            && hand[4][RANK] == 12) {
            wheel = true;
        }
    }

    /* check for 4-of-a-kind, 3-of-a-kind, and pairs */
    int card = 0;
    while(card < NUM_CARDS) {
        int run = 0;
        rank = hand[card][RANK];
        do {
            run++;
            card++;
        } while (card < NUM_CARDS && rank == hand[card][RANK]);

        switch (run) {
            case 2: pairs++; break;
            case 3: three = true; break;
            case 4: four = true; break;
        }
    }


}
void print_result(void) {
    if(royal) printf("Royal Flush");
    else if(straight && flush) printf("Straight flush");
    else if(wheel) printf("Wheel");
    else if(four) printf("Four of a kind");
    else if(three &&
            pairs == 1) printf("Full house");
    else if(flush)      printf("Flush");
    else if(straight)   printf("Straight");
    else if(three)      printf("Three of a kind");
    else if(pairs == 2) printf("Two pairs");
    else if(pairs == 1) printf("Pair");
    else                printf("High card");
    printf("\n\n");
}